/*
 * Copyright (c)  2020,  DataPipeline
 * All rights reserved.
 *
 * Id:MarkDownParser.java   2020-07-18 10:48 wanglijun
 */
package cn.datacare.orm.loader;

import cn.datacare.orm.source.SQLSource;
import cn.datacare.orm.util.Separator;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import static cn.datacare.orm.util.Separator.*;

/**
 * <p>
 * Title: MarkDownParser
 * </p>
 * <p>
 * Description: MarkDownParser 文件解析
 * </p>
 * <p>
 * Copyright: Copyright (c) 2020
 * </p>
 * <p>
 * Company/Department: DataPipeline
 * </p>
 *
 * @author wanglijun
 * @version 1.0
 * @since 2020-07-18 10:48
 */
public class MarkDownParser {
    /***
     * MD文件==== {@value}
     */
    public static final String MD_START = EQUALS_SIGN + EQUALS_SIGN + EQUALS_SIGN;
    /**
     * MD ~~~ {@value}
     */
    public static final String MD_TILDES = TILDE + TILDE + TILDE;
    /***
     * 反引号 ``` {@value}
     */
    public static final String MD_BACK_QUOTES = BACK_QUOTE + BACK_QUOTE + BACK_QUOTE;
    private static int END = 1;
    private BufferedReader br;
    private String modelName;
    private int linNumber;
    private String lastLine;
    private String lastLastLine;
    private int status = 0;

    public MarkDownParser(String modelName, BufferedReader br) throws IOException {
        this.modelName = modelName;
        this.br = br;
        skipHeader();
    }


    public void skipHeader() throws IOException {
        while (true) {
            String line = this.nextLine();
            if (status == END) {
                return;
            }
            if (line.startsWith(MD_START)) {
                return;
            }

        }
    }

    public SQLSource next() throws IOException {
        String sqlId = this.readSqlId();
        if (status == END) {
            return null;
        }
        //去掉可能的尾部空格
        sqlId = sqlId.trim();
        skipComment();
        if (status == END) {
            return null;
        }
        int sqlLine = this.linNumber;
        String sql = readSql();

        SQLSource source = new SQLSource(modelName + sqlId, sql);
        source.setLine(sqlLine);
        return source;
    }

    /***
     * 跳过备注
     * @throws IOException
     */
    public void skipComment() throws IOException {
        boolean findComment = false;
        while (true) {
            String line = nextLine();
            if (status == END) {
                return;
            }
            line = line.trim();
            if (!findComment && line.length() == 0) {
                continue;
            }
            if (line.startsWith(Separator.ASTERISK)) {
                //注释符号
                findComment = true;
                continue;
            } else {
                String s = line.trim();
                if (s.length() == 0) {
                    continue;
                } else if (s.startsWith(MD_BACK_QUOTES) || s.startsWith(MD_TILDES)) {
                    //忽略以code block开头的符号
                    continue;
                } else {
                    //注释结束
                    return;
                }

            }
        }
    }

    public String readSql() throws IOException {
        List<String> list = new LinkedList<>();
        list.add(lastLine);
        while (true) {
            String line = nextLine();

            if (status == END) {
                return getBuildSql(list);
            }

            if (line.startsWith(MD_START)) {
                //删除下一个sqlId表示
                list.remove(list.size() - 1);
                return getBuildSql(list);
            }
            list.add(line);

        }
    }

    private String getBuildSql(List<String> list) {
        StringBuilder sb = new StringBuilder();
        for (String str : list) {
            String s = str.trim();
            if (s.startsWith(MD_TILDES) || s.startsWith(MD_BACK_QUOTES)) {
                //忽略以code block开头的符号
                continue;
            }
            sb.append(str).append(Separator.LINE_BREAK);
        }
        return sb.toString();
    }

    public String readSqlId() {
        return lastLastLine;
    }

    public String nextLine() throws IOException {
        String line = br.readLine();
        linNumber++;
        if (line == null) {
            status = END;

        }
        //保存最后读的俩行
        lastLastLine = lastLine;
        lastLine = line;
        return line;
    }
}
